'use strict';

const createConfig = require('uni-config-center');
const uidConfig = createConfig({
	pluginId: 'uni-id'
});

const uidPay = require('uni-pay');

const db = uniCloud.database();

exports.main = async (event, context) => {
	let response = {
		mpserverlessComposedResponse: true,
		statusCode: 200,
		headers: {
			'content-type': 'text/xml;charset=utf-8'
		},
		body: `<xml><return_code><![CDATA[FAILD]]></return_code><return_msg><![CDATA[异常回调]]></return_msg></xml>`
	};
	
	uniCloud.logger.info('notify', event);
	
	const path = event.path;
	let res = {};
	
	let notifyType = 'payment';
	let payObj = {
		name: '微信支付',
		way: 'wxpay'
	};
	switch (path) {
		case '/':
		case '/wxpay':
		case '/wxpay-app':
		case '/wxpay-h5wx':
			let wxpayConfig;
			if (path == '/wxpay-app') {
				wxpayConfig = uidConfig.config('app.wxpay');
			} else if (path == '/wxpay-h5wx') {
				wxpayConfig = uidConfig.config('h5-weixin.pay');
			} else {
				wxpayConfig = uidConfig.config('mp-weixin.pay');
			}
			const uniWxpayIns = uidPay.initWeixin(wxpayConfig);
			res = await uniWxpayIns.verifyPaymentNotify(event);
		
			break;
		case '/alipay':
		case '/alipay-app':
			let alipayConfig = uidConfig.config('mp-alipay.pay');
			if (path == '/alipay-app') {
				alipayConfig = uidConfig.config('app.alipay');
			}
			const uniAlipayIns = uidPay.initAlipay(alipayConfig);
			notifyType = await uniAlipayIns.checkNotifyType(event)
			if (notifyType === 'refund') {
				// 退款通知
			} else if (notifyType === 'payment') {
				// 支付结果通知
			}
			uniCloud.logger.info(notifyType);
			
			res = await uniAlipayIns.verifyPaymentNotify(event);

			payObj.name = '支付宝支付';
			payObj.way = 'alipay';
			break;
		default:
			break;
	}

	// 根据支付订单号获取订单数据
	// 根据创建订单用户ID获取用户数据
	// 记录用户充值金额、写入用户零钱
	// 发送零钱到账消息通知
	if (res && (res.returnCode == 'SUCCESS' || res.resultCode == 'SUCCESS') && notifyType == 'payment') {
		const {
			outTradeNo,
			totalFee,
			transactionId,
			openid
		} = res;
		
		// 根据支付订单号获取订单数据
		const orderRes = await db.collection('usemall-member-pay')
			.doc(outTradeNo)
			.get();

		const [orderPay] = orderRes.data;
		if (!orderPay) {
			uniCloud.logger.info(`订单[${outTradeNo}]不存在`);
			return response;
		}
		if (orderPay.pay_state != '待付款') {
			uniCloud.logger.info(`订单[${outTradeNo}]状态[${orderPay.pay_state}]`);
			return response;
		}
		
		
		const nowdate = Date.now();
		const ip = event.headers['x-real-ip'];
		
		// 优先将订单支付状态修改为待核实
		await db.collection('usemall-member-pay').doc(orderPay._id).update({
			version: db.command.inc(1),
			pay_state: '待核实',
			pay_notify: event,
			pay_no: transactionId,
			pay_openid: openid,
			ip,
			//yymm: ,
			//yymmdd: ,
			pay_time: nowdate
		});
		
		if (orderPay.pay_money * 100 != totalFee) {
			uniCloud.logger.info(`订单[${outTradeNo}]支付金额不一致，[${orderPay.pay_money * 100}] != [${totalFee}]`);
			return response;
		}
		
		// 创建订单用户ID
		const uid = orderPay.create_uid;
		// 根据创建订单用户ID获取用户数据
		const userRes = await db.collection('usemall-member')
			.doc(uid)
			.field({
				member_nickname: true,
				member_mobile: true,
				member_type: true,
				member_weixin: true,
				member_alipay: true,
				member_amount: true
			})
			.get();
		if (!(userRes.data && userRes.data.length == 1)) {
			uniCloud.logger.info(`订单[${outTradeNo}]对应的用户不存在`);
			return response;
		}
		// 用户
		const user = userRes.data[0];
		const uname = user.member_nickname;
		
		// 开启事务
		const dbtran = await db.startTransaction();
		
		try {
			
			// 修改订单支付数据
			await dbtran.collection('usemall-member-pay').doc(outTradeNo).update({
				version: db.command.inc(1),
				pay_state: '已付款',
				pay_notify: event,
				pay_no: transactionId,
				pay_openid: openid,
				pay_way: payObj.name,
				ip,
				//yymm: ,
				//yymmdd: ,
				pay_time: nowdate
			});
			
			// 记录用户充值金额、写入用户零钱
			await dbtran.collection('usemall-member').doc(uid).update({
				member_amount: db.command.inc(orderPay.pay_money * 100)
			});
			let content = `通过${payObj.name}充值+${orderPay.pay_money}`;
			
			const payLogRes = await dbtran.collection('usemall-member-money-log').doc(outTradeNo).get();
			const payLog = payLogRes.data;
			if (payLog && payLog._id) {
				await dbtran.collection('usemall-member-money-log').doc(payLog._id).update({
					user_uid: uid,
					order_id: outTradeNo,
					money: orderPay.pay_money,
					money_fmt: '+' + orderPay.pay_money,
					source: payObj.name,
					state: '已付款',
					type: '充值',
					remark: content,
					ip: ip,
					is_delete: 0,
					create_uid: uid,
					create_uname: uname,
					create_time: nowdate
				});
			} else {
				await dbtran.collection('usemall-member-money-log').doc(outTradeNo).set({
					user_uid: uid,
					order_id: outTradeNo,
					money: orderPay.pay_money,
					money_fmt: '+' + orderPay.pay_money,
					source: payObj.name,
					state: '已付款',
					type: '充值',
					remark: content,
					ip: ip,
					is_delete: 0,
					create_uid: uid,
					create_uname: uname,
					create_time: nowdate
				});
			}
			
			
			// 提交事务
			await dbtran.commit();
			
		} catch(e) {
			await db.collection('usemall-member-pay').doc(orderPay._id).update({
				version: db.command.inc(1),
				pay_state: '待付款'
			});
			
			// 事务回滚
			await dbtran.rollback();
			uniCloud.logger.info(`订单[${outTradeNo}]支付回调处理异常 ${e.message}`);
			return response;
		}
		
		if (payObj.way == 'wxpay') {
			response.body = `<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>`;
		} else if (payObj.way == 'alipay') {
			response.headers['content-type'] = 'text/plain';
			response.body = 'success';
		}
	}
	
	if (notifyType == 'refund') {
		if (payObj.way = 'alipay') {
			response.headers['content-type'] = 'text/plain';
			response.body = 'success';
		}
	}

	uniCloud.logger.info(res);
	uniCloud.logger.info(response);

	return response;
};

/**
 * 将 UTC+0 转换为 UTC+8
 */
function toDateUTC8(date) {
	if (uniCloud.$provider == 'alipay') {
		// 支付宝云，默认为 UTC+8
		return date;
	}
	
	// 小时 UTC+0 转换为 UTC+8
	date.setHours(date.getHours() + 8);
	return date;
}


const uDelay = async (sec) => {
	return new Promise((c1, c2) => {
		console.log('uDelay sec', sec);
		setTimeout(() => {
			c1();
			console.log('uDelay sec success', sec);
		}, sec * 1000);
	});
}